// Infrastructure/Services/FileManager.cs
using MediatR;
using Microsoft.Extensions.Options;
using UniversalAdmin.Application.Common;
using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Application.Services;
using UniversalAdmin.Domain.Interfaces;
using UniversalAdmin.Infrastructure.Options;

namespace UniversalAdmin.Infrastructure.Services;

public sealed class FileService : IFileService
{
  private readonly IUnitOfWork _uow;
  private readonly FileStorageOptions _opt;
  private readonly IAuthService _authService;

  public FileService(IUnitOfWork uow, IOptions<FileStorageOptions> opt, IAuthService authService)
  {
    _uow = uow;
    _opt = opt.Value;
    _authService = authService;
  }

  public async Task<ApiResult<FileDto>> UploadAsync(
      Stream stream, string originalName, string contentType,
      long length, int userId, CancellationToken ct = default)
  {
    Console.WriteLine($"FileService.UploadAsync called with: name={originalName}, type={contentType}, size={length}, userId={userId}");
    try
    {

      if (length == 0) 
      {
        Console.WriteLine("文件大小为0");
        return ApiResult<FileDto>.Failure(400, "空文件");
      }
      if (length > _opt.MaxBytes) 
      {
        Console.WriteLine($"文件过大: {length} > {_opt.MaxBytes}");
        return ApiResult<FileDto>.Failure(413, "文件过大");
      }

      // 1. 检查流是否可用
      if (stream == null || stream.CanRead == false)
      {
        Console.WriteLine("无效的文件流");
        return ApiResult<FileDto>.Failure(400, "无效的文件流");
      }

      await using var memoryStream = new MemoryStream();
      await stream.CopyToAsync(memoryStream, ct);
      memoryStream.Position = 0; // 重置流位置

      // 3. 继续处理文件...
      var ext = Path.GetExtension(originalName).ToLowerInvariant();
      Console.WriteLine($"文件扩展名: {ext}");
      Console.WriteLine($"允许的扩展名: {string.Join(", ", _opt.AllowedExtensions)}");
      
      if (!_opt.AllowedExtensions.Contains(ext))
      {
        Console.WriteLine($"不支持的文件类型: {ext}");
        return ApiResult<FileDto>.Failure(415, "不支持的文件类型");
      }

      var datePart = DateTime.UtcNow.ToString("yyyy/MM/dd");
      var dir = Path.Combine(_opt.RootPath, datePart);
      
      Console.WriteLine($"存储目录: {dir}");
      Console.WriteLine($"根路径: {_opt.RootPath}");
      
      Directory.CreateDirectory(dir);
      Console.WriteLine("目录创建成功");
      var safeFileName = Path.GetInvalidFileNameChars()
          .Aggregate(originalName, (current, c) => current.Replace(c.ToString(), "_"));

      var storedName = $"{Guid.NewGuid():N}_{safeFileName}";
      var relativePath = $"{datePart}/{storedName}";
      var fullPath = Path.Combine(dir, storedName);

      await using var fs = new FileStream(fullPath, FileMode.Create);
      await memoryStream.CopyToAsync(fs, ct);
      // await stream.CopyToAsync(fs, ct);

      var entity = new Domain.Entities.File
      {
        Name = storedName,
        OriginalName = originalName,
        Path = relativePath,
        Size = length,
        MimeType = contentType,
        UserId = userId,
        CreatedAt = DateTime.UtcNow
      };

      await _uow.FileRepository.AddAsync(entity);
      await _uow.SaveChangesAsync();

      var dto = new FileDto
      {
        Id = entity.Id,
        Name = storedName,
        OriginalName = originalName,
        Path = relativePath,
        Url = $"/uploads/{relativePath}", // 添加完整的URL路径
        Size = length,
        MimeType = contentType,
        CreatedAt = entity.CreatedAt
      };
      return ApiResult<FileDto>.Success(dto, "上传成功");
    }
    catch (Exception ex)
    {
      Console.WriteLine("Upload error: " + ex.Message);
      throw;
    }
  }

  public async Task<PagedResult<FileDto>> GetFilesAsync(
      FileQueryParameters p, CancellationToken ct = default)
  {
    var paged = await _uow.FileRepository.SearchFilesAsync(
        keyword: p.Keyword,
        mimeType: p.MimeType,
        userId: p.UserId,
        pageIndex: p.Page,
        pageSize: p.Size);

    var dtos = paged.Items.Select(f => new FileDto
    {
      Id = f.Id,
      Name = f.Name,
      OriginalName = f.OriginalName,
      Path = f.Path,
      Size = f.Size,
      UserId = f.UserId,
      Username = f.User?.Username,
      MimeType = f.MimeType ?? "",
      CreatedAt = f.CreatedAt
    }).ToList();

    return new PagedResult<FileDto>
    {
      Items = dtos,
      TotalCount = paged.TotalCount,
      PageIndex = p.Page,
      PageSize = p.Size
    };
  }

  public async Task<ApiResult<FileDto>> GetFileByIdAsync(int id, int actorUserId, CancellationToken ct = default)
  {
    var file = await _uow.FileRepository.GetByIdAsync(id);
    if (file is null) return ApiResult<FileDto>.Failure(404, "文件不存在");

    // 权限判断
    var userRoles = await _authService.GetUserRolesAsync(actorUserId);
    var isAdmin = userRoles.Contains("Admin") || userRoles.Contains("SuperAdmin");

    if (file.UserId != actorUserId && !isAdmin)
      return ApiResult<FileDto>.Failure(403, "只能获取自己的文件");

    var dto = new FileDto
    {
      Id = file.Id,
      Name = file.Name,
      OriginalName = file.OriginalName,
      Path = file.Path,
      Size = file.Size,
      MimeType = file.MimeType ?? "",
      CreatedAt = file.CreatedAt
    };
    return ApiResult<FileDto>.Success(dto, "获取成功");
  }


  public async Task<ApiResult<Unit>> DeleteAsync(
      int fileId, int actorUserId, CancellationToken ct = default)
  {
    var file = await _uow.FileRepository.GetByIdAsync(fileId);
    if (file is null) return ApiResult<Unit>.Failure(404, "文件不存在");
    if (file.UserId != actorUserId)
      return ApiResult<Unit>.Failure(403, "只能删除自己的文件");

    // 获取当前用户角色
    var userRoles = await _authService.GetUserRolesAsync(actorUserId);
    var isAdmin = userRoles.Contains("Admin") || userRoles.Contains("SuperAdmin");

    if (!isAdmin && file.UserId != actorUserId)
      return ApiResult<Unit>.Failure(403, "无权删除此文件");

    var fullPath = Path.Combine(_opt.RootPath, file.Path.TrimStart('/'));
    if (System.IO.File.Exists(fullPath)) System.IO.File.Delete(fullPath);

    await _uow.FileRepository.RemoveAsync(file);
    await _uow.SaveChangesAsync();

    return ApiResult<Unit>.Success(Unit.Value, "删除成功");
  }

}